package test.threads.queue.unstressed.impl;


/**
 * Queue implementation:
 * Circular array based
 * Concurrent (single-enq, single-deq)
 * Bounded
 * Blocking (by spin-wait)
 * <p/>
 *
 * @author cheremin
 * @since 21.09.11,  13:56
 */
public final class CABSESDLongQueue extends AbstractSESDSequencer {

    private static final int PAD = 1;
    private static final boolean OPTIMIZE_INDEX = true;


    private final long[] elements;

    private final int mask;


    @SuppressWarnings( "unchecked" )
    public CABSESDLongQueue( final int size ) {
        super( size );
        if ( OPTIMIZE_INDEX ) {
            if ( Integer.bitCount( size ) != 1 ) {
                throw new IllegalArgumentException( "size (" + size + ") must be a power of 2" );
            }
            mask = size - 1;
        } else {
            mask = -1;
        }
        elements = new long[size * PAD];
    }

    public void enqueue( final long item ) {
        final long newTail = nextTail();

        final int index = index( newTail - 1 );
        elements[index] = item;

        publishTail( newTail );
    }

    public long dequeue() {
        final long newHead = nextHead();

        final int index = index( newHead - 1 );
        final long item = elements[index];

        publishHead( newHead );
        return item;
    }

    private int index( final long sequence ) {
        if ( OPTIMIZE_INDEX ) {
            return ( int ) ( sequence & mask ) * PAD;
        } else {
            return ( int ) ( sequence % length() ) * PAD;
        }
    }
}
